#include "amever.h"

inline char_init(struct client *me) {
		if (!me->achar) {
			me->achar = malloc(sizeof(struct world_char));
		}
		memset(me->achar, 0, sizeof(struct world_char));
		me->achar->client = me;
		me->achar->id = atoi(s.sql_row[0]);
		strcpy(me->achar->name, s.sql_row[1]);
		me->achar->props.sex = atoi(s.sql_row[2]);
		me->achar->props.class_id = atoi(s.sql_row[3]);
		me->achar->props.lvl = atoi(s.sql_row[4]);
		me->achar->props.exp = atoi(s.sql_row[5]);
		me->achar->props.speed = atoi(s.sql_row[6]);
		me->achar->stats.wspeed = atoi(s.sql_row[6]);
		printf("My speed is %d\n", atoi(s.sql_row[6]));
		me->achar->position = 0;
		me->achar->steps = 0;
		if (!s.chars)
			s.chars = chain_setInit(0, 0, MAX_CLIENTS);
		me->achar->global_hook = chain_insertUnique(s.chars, me->achar->id, me->achar, 0);
}

void char_shut(struct client *me) {
	if (me->achar->position)
		chain_nodeShut(me->achar->position);
	if (me->achar->global_hook)
		chain_nodeShut(me->achar->global_hook);
	if (me->achar->steps) {
		chain_setShut(me->achar->steps);
		me->achar->steps = 0;
	}
	memset(me->achar, 0, sizeof(struct world_char));
	free(me->achar);
	me->achar = 0;
}

int char_walk(struct world_char *me) {
	if (me->steps==0 || me->steps->first==0)
		return 0;
	/* Calc next cell */
	int x0 = me->cell->X, y0 = me->cell->Y, x1 = CELL(me->steps->first->val)->X, y1 = CELL(me->steps->first->val)->Y;
	amelog("Calculating the next step from %d:%d to %d:%d\n",
		x0, y0, x1, y0);
	return 0;
}

void char_sees(struct world_char *me, WorldObject type, void *what) {
	switch (type) {
		case WO_CHAR :
			WFIFOPR(me->client, 8);
			WFIFOW(me->client, 0) = 20;
			WFIFOW(me->client, 2) = CHAR(what)->id;
			WFIFOW(me->client, 4) = CHAR(what)->cell->X;
			WFIFOW(me->client, 6) = CHAR(what)->cell->Y;
			WFIFOSP(me->client, 8);
			
			WFIFOPR(CHAR(what)->client, 8);
			WFIFOW(CHAR(what)->client, 0) = 20;
			WFIFOW(CHAR(what)->client, 2) = me->id;
			WFIFOW(CHAR(what)->client, 4) = me->cell->X;
			WFIFOW(CHAR(what)->client, 6) = me->cell->Y;
			WFIFOSP(CHAR(what)->client, 8);
			return;
	}
}

void char_debugSteps (struct world_char *c) {
	struct chain_node *node;
	amelog("Steps debug : ");
	for (node=c->steps->first;node;node = node->next) {
		amelog("%d:%d ", ((struct world_cell *)node->val)->X, ((struct world_cell *)node->val)->Y);
	}
	amelog("\n");
}


int char_do (struct world_char *c) {
	struct world_cell *cell = 0;
	switch (c->status.action) {
		case CHA_WALKING:
			char_debugSteps(c);
			cell = char_getNextCell(c);

			if (cell == 0) {
				amelog("Next cell is 0\n");
				chain_nodeShut(c->steps->first);
				char_stop(c);
				return;
			}

			char_setPosition(c, cell);

			if (!c->steps->first) {
				char_stop(c);
				return;
			}

			c->status.nextAction = s.clock + (1000 / (c->props.speed/50));
			amelog("Speed is %d\n", c->props.speed);

		return 0;
	}	
}

inline void char_setPosition(struct world_char *c, struct world_cell *cell) {
	CHAIN_UNLINK(c->position);
	c->cell = cell;
	if (!c->cell->objects)
	c->cell->objects = chain_setInit(0,0,255);
	chain_nodeInit(c->cell->objects, 0, 0, c->position);
}

int char_stop(struct world_char *c) {
	amelog("Stopping char on %d:%d\n", c->cell->X, c->cell->Y);
	c->status.action = CHA_STAYINGBY;
	if (c->steps->first)
		chain_setClear(c->steps);

	struct chain_set *tmp = chain_setInit(0,0,255);
	if (map_foreach(WO_CHAR, c->cell, CHAR_RADIUS, tmp)) {
		struct chain_node *node;
		for (node=tmp->first;node;node = node->next) {
			WFIFOPR(CHAR(node->val)->client, 8);
			WFIFOW(CHAR(node->val)->client, 0) = 20;
			WFIFOW(CHAR(node->val)->client, 2) = c->id;
			WFIFOW(CHAR(node->val)->client, 4) = c->cell->X;
			WFIFOW(CHAR(node->val)->client, 6) = c->cell->Y;
			WFIFOSP(CHAR(node->val)->client, 8);
		}
	}
	chain_setShut(tmp);

	return 0;
}

struct world_cell *char_getNextCell(struct world_char *c) {
	if (!c->steps || !c->steps->first)
		amelog("No steps.\n");
	if ( !c || !c->steps || !c->steps->first )
		return (struct world_cell *)0;
	else if ( (struct world_cell *)c->steps->first->val == c->cell ) {
		chain_nodeShut(c->steps->first);
		if (!c->steps->first)	{
			return (struct world_cell *)0;
		}
	}
	
	struct world_cell *cnext = (struct world_cell *)c->steps->first->val;
	unsigned short x = c->cell->X; unsigned short y = c->cell->Y;

	if (cnext->X - c->cell->X != 0)
		x += (cnext->X - c->cell->X > 0 ? 1 : -1);
	if (cnext->Y - c->cell->Y != 0)
		y += (cnext->Y - c->cell->Y > 0 ? 1 : -1);

	if (x > c->cell->wmap->width || y > c->cell->wmap->height || c->cell->wmap->cells[y][x]->passable == 0)
	{
		if (c->cell->wmap->cells[y][x]->passable == 0)
			amelog("The cell %d:%d is unpassable.\n", x,y);
		return 0;
	}
	amelog("Next cell is : %d %d and the last cell is \n", x, y);
	if (c->cell->wmap->cells[y][x] == (struct world_cell *)c->steps->last->val) {
		amelog("IN the last cell.\n");
		chain_nodeShut(c->steps->first);
	}
	return c->cell->wmap->cells[y][x];
}
